home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
source
/
vesavga
/
vga.asm
< prev
Wrap
Assembly Source File
|
1992-06-19
|
14KB
|
855 lines
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; Title: vga.asm
; Date: 6/18/92
; Author: Randy Buckland (randy@ncsu.edu)
;
; Description:
; This is a VERY basic set of routines to provide high speed SVGA
; graphics for IBM-PC compatibiles that have a VGA interface that supports
; a VESA driver. These routines assume a 256-color mode and will not work
; for any type of mode. The following routines are provided:
;
; vgainit(int vesa_mode)
; vgapoint(int row, int column, int pixel_value)
; vgahline(int row, int start_column, int end_column, int pixel_value)
; vgaline(int x1, int y1, int x2, int y2, int pixel_value)
; vgasetcolor(char *colors, int start, int count)
; vgafill(int row, int column, int width, int height, int pixel_value)
; vgarect(char *source, int source_width, int row, int column,
; int width, int height)
;
; Copyright (c) 1992 by Randy Buckland
; Permission is given to use this code in any manner desired with the
; following provisions:
; 1. The user of the code is totally responsible for any damages
; that may be caused by it's use.
; 2. The author has no control or responsibility for any damages
; that may be caused by it's use.
; 3. This copyright notice must remain a part of this source file.
;
.model large,c
include macros.asm
;
; Global data for the VGA support routines
;
vgadata segment word public 'VGADATA'
Block dw 1 ; Current video memory block accessable
BlockSz dw 0 ; Size of a video block in K
BlockShift dw 0 ; Amount to shift bits by
BlockEnd dw 0 ; Last valid address in block
BlockMask dw 0 ; Mask used for block/offset operations
WinAddr dw 0 ; Segment addr of window A block
;WinFunc dd 0 ; Far pointer to windowing function
ScanWidth dw 0 ; Width of a scan line
vgadata ends
vgacode segment word public 'VGACODE'
assume cs:vgacode,ds:vgadata
;
; Set current video memory block. This procedure assumes that ds already
; points to the vgadata segment. This routine will not modify any registers.
;
; Parameters:
; - block number to change to
;
vgablock proc near
push bp
mov bp,sp
push dx
mov dx,[bp+4] ; Start of video memory
cmp dx,Block
je l1
mov Block,dx
push ax
push bx
mov ax,4f05h ; VESA set memory block
mov bx,0000h ; Set window A
int 10h
pop bx
pop ax
l1:
pop dx
mov sp,bp
pop bp
ret
vgablock endp
;
; Calculate block and offset values for a given row/column. Assumes that ds
; points to vgadata. Does NOT preserve registers. Returns block value in
; dx and offset in ax.
;
; Parameters:
; - row value
; - column value
;
vgaoffset proc near
push bp
mov bp,sp
mov ax,[bp+4] ; Get row
mul ScanWidth ; Get starting block and offset in dx:ax
add ax,[bp+6] ; Add start column offset
jnc l1
inc dx ; Just crossed block boundery
l1:
mov cx,BlockShift ; Get block size mask
cmp cx,0 ; Is block size 64K?
je l2 ; Yes, skip this section
mov bx,ax ; Save old ax
rol ax,cl
and ax,BlockMask ; Save high bits
rol dx,cl
add dx,ax ; Add high bits to block value.
mov ax,bx
rol ax,cl
or ax,BlockMask ; Set undesirable bits
xor ax,BlockMask ; Clear bad bits
ror ax,cl
;
; Set active block to calculated block if needed
;
l2:
cmp dx,Block
je l3
push dx
call vgablock
pop dx
l3:
mov sp,bp
pop bp
ret
vgaoffset endp
;
; Initialize the display
; Parameters:
; Mode value to use
;
public vgainit
vgainit proc far
;
; Set up call frame
;
Prefix
sub sp,256 ; Make local variable space
;
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Get VGA information and set desired mode
;
mov ax,4f02h ; VESA set mode function
mov bx,[bp+6] ; 640x480 mode
int 10h
push ss
pop es ; Load es with value of ss
mov di,sp ; Point index at 256 byte temp space
mov cx,[bp+6]
mov ax,4f01h ; VESA get Super VGA mode information
int 10h
mov ax,es:[di+6]
mov BlockSz,ax
mov ax,es:[di+8]
mov WinAddr,ax
; mov ax,es:[di+12]
; mov word ptr WinFunc,ax
; mov ax,es:[di+14]
; mov word ptr WinFunc+2,ax
mov ax,es:[di+16]
mov ScanWidth,ax
;
; Calculate block shift and end values
;
mov ax,BlockSz
mov bx,10
mov cx,03ffh
l1:
sar ax,1
inc bx
sal cx,1
inc cx
cmp ax,1
ja l1
mov ax,16
sub ax,bx
mov BlockShift, ax
mov BlockEnd, cx
not cx
xchg ax,cx
rol ax,cl
mov BlockMask,ax
;
; Set to start block
;
xor ax,ax
push ax
call vgablock
pop ax
;
; Remove call frame and exit
;
add sp,256
Postfix
vgainit endp
;
; Draw a single point
;
; Parameters:
; - Row of point
; - Column of point
; - Pixel value to use
;
vgapoint proc far
Prefix
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Load window pointers
;
mov ax,WinAddr
mov es,ax ; Set ES to point to video memory
push [bp+8] ; Column
push [bp+6] ; Row
call vgaoffset
add sp,4
;
; Draw point
;
mov di,ax ; Put offset in index regester
mov ax,[bp+10] ; bl has pixel value
cld
stosb
Postfix
vgapoint endp
;
; Draw a horizontal line. Line is assumed to start on even boundry and
; have length be an even value for speed.
;
; Parameters:
; - Row for line
; - Start column
; - End column
; - Pixel value
;
vgahline proc far
Prefix
;
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Load window pointers
;
mov ax,WinAddr
mov es,ax ; Set ES to point to video memory
push [bp+8]
push [bp+6]
call vgaoffset
add sp,4
;
; Setup control parameters for line draw.
;
mov di, ax ; Offset in di
mov ax,[bp+12]
mov ah,al ; ax has duplicated pixel value in bl and bh
mov cx,BlockEnd ; Last point in counter
sub cx,di ; cx has number of legal bytes-1
mov bx,[bp+10]
sub bx,[bp+8] ; bx has number to write - 1
cmp bx,cx
ja l1
mov cx,bx ; Won't need a block change
l1:
sub bx,cx ; ax has number of words after block change
inc cx
ror cx,1
ror bx,1
;
; Draw the line
;
even
l4:
cld
rep stosw
cmp bx,0
je l5
;
; Handle block change and continue
;
inc dx
push dx
call vgablock
pop dx
mov cx,bx
xor bx,bx
xor di,di
jmp l4
;
; Finish up
;
l5:
Postfix
vgahline endp
;
; Draw a line using bresenham's algorithm.
;
; Parameters:
; - x1
; - y1
; - x2
; - y2
; - Pixel value
;
; Locals:
; [bp-10] DX
; [bp-12] DY
; [bp-14] incr1
; [bp-16] incr2
;
vgaline proc far
Prefix
sub sp,8
;
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Load window pointers
;
mov ax,WinAddr
mov es,ax ; Set ES to point to video memory
push [bp+8]
push [bp+6]
call vgaoffset
add sp,4
mov di,ax
;
; Initialize for line draw
;
mov ax,[bp+6] ; Get x1
sub ax,[bp+10] ; Sub x2
jg l1 ; Skip if positive
neg ax
l1: mov [bp-10],ax ; Save DX
mov ax,[bp+8] ; Get y1
sub ax,[bp+12] ; sub y2
jg l2 ; Skip if positive
neg ax
l2: mov [bp-12],ax ; Save DY
cmp ax,[bp-10] ; See if DY>DX
jle xline ; Go do X oriented version
jmp yline ; Go do Y oriented version
;
; X oriented version of draw line. Slope must be between -1 and 1 inclusive
;
xline:
mov cx, [bp-10] ; cx has increment control
sal ax,1 ; DY*2
mov [bp-14],ax ; Save incr1
sub ax,[bp-10] ; 2*dy - dx
mov bx,ax ; bx has D value
mov ax,[bp-12] ; Get DY
sub ax,[bp-10] ; (DY-DX)
sal ax,1 ; 2*(DY-DX)
mov [bp-16],ax ; Save incr2
mov word ptr [bp-10],0 ; Assume going to left
mov ax,[bp+6] ; Get x1
sub ax,[bp+10] ; x1-x2
jg l3
mov word ptr [bp-10],1 ; Going to right
l3:
mov word ptr [bp-12],0 ; Assume going up
mov ax,[bp+8] ; Get y1
sub ax,[bp+12] ; y1-y2
jg l5
mov word ptr [bp-12],1 ; Going down
l5:
;
; Main X oriented drawing loop.
; ax = pixel value
; bx = d
; cx = loop control
; dx = block number
; di = block offset
;
mov ax,[bp+14]
mov es:[di],al ; Write first pixel
cmp cx,0 ; Check if done
je xloopend
xloop:
cmp word ptr [bp-10],0 ; See if going left?
je l7
inc di ; going right
jnc l8
inc dx
push dx
call vgablock
pop dx
jmp l8
l7:
dec di ; going left
jnc l8
dec dx
push dx
call vgablock
pop dx
l8:
cmp bx,0 ; test d<0
jge l9
add bx,[bp-14] ; d = d + incr1
jmp l11
l9:
add bx,[bp-16] ; d = d + incr2
cmp word ptr [bp-12],0 ; See if going up
je l10
add di,ScanWidth ; Go to next line
jnc l11
inc dx
push dx
call vgablock
pop dx
jmp l11
l10:
sub di,ScanWidth ; Go to previous line
jnc l11
dec dx
push dx
call vgablock
pop dx
l11:
mov es:[di],al ; Write next pixel
loop xloop
xloopend:
jmp done
;
; Y oriented version of draw line. Slope must be outside -1 and 1 inclusive
;
yline:
mov cx, [bp-12] ; cx has increment control
mov ax, [bp-10]
sal ax,1 ; DX*2
mov [bp-14],ax ; Save incr1
sub ax,[bp-12] ; 2*dx - dy
mov bx,ax ; bx has D value
mov ax,[bp-10] ; Get DX
sub ax,[bp-12] ; (DX-DY)
sal ax,1 ; 2*(DX-DY)
mov [bp-16],ax ; Save incr2
mov word ptr [bp-10],0 ; Assume going to left
mov ax,[bp+6] ; Get x1
sub ax,[bp+10] ; x1-x2
jg l12
mov word ptr [bp-10],1 ; Going to right
l12:
mov word ptr [bp-12],0 ; Assume going up
mov ax,[bp+8] ; Get y1
sub ax,[bp+12] ; y1-y2
jg l13
mov word ptr [bp-12],1 ; Going down
l13:
;
; Main Y oriented drawing loop.
; ax = pixel value
; bx = d
; cx = loop control
; dx = block number
; di = block offset
;
mov ax,[bp+14]
mov es:[di],al ; Write first pixel
cmp cx,0 ; Check if done
je yloopend
yloop:
cmp word ptr [bp-12],0 ; See if going up?
je l14
add di,ScanWidth ; going down
jnc l15
inc dx
push dx
call vgablock
pop dx
jmp l15
l14:
sub di,ScanWidth ; going up
jnc l15
dec dx
push dx
call vgablock
pop dx
l15:
cmp bx,0 ; test d<0
jge l16
add bx,[bp-14] ; d = d + incr1
jmp l18
l16:
add bx,[bp-16] ; d = d + incr2
cmp word ptr [bp-10],0 ; See if going left
je l17
inc di ; Go right
jnc l18
inc dx
push dx
call vgablock
pop dx
jmp l18
l17:
dec di ; Go left
jnc l18
dec dx
push dx
call vgablock
pop dx
l18:
mov es:[di],al ; Write next pixel
loop yloop
yloopend:
;
; Clear stack and exit
;
done:
add sp,8
Postfix
vgaline endp
;
; Set colors from an array of rgb values.
;
; Parameters:
; - Array of colors
; - Start index
; - Number of colors
;
vgasetcolor proc far
Prefix
les dx,[bp+6] ; Get address of colormap
mov bx,[bp+10] ; Get first color index
mov cx,[bp+12] ; Get Number of indexes
mov ax,1012h ; Set block of color registers function
int 10h
Postfix
vgasetcolor endp
;
; Fill a rectangular region with a given pixel value. Region is assumed to
; start on a even address and be an even width. Width and height values
; must be positive. Width and height values get modified.
;
; Parameters:
; - Row for upper left corner
; - Column for upper left corner
; - Width of rectangle
; - Height of rectangle
; - Pixel value
;
; Locals
; [bp-10] LineSkip
;
vgafill proc far
Prefix
sub sp,2
;
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Load window pointers
;
mov ax,WinAddr
mov es,ax ; Set ES to point to video memory
push [bp+8]
push [bp+6]
call vgaoffset
add sp,4
;
; Setup control parameters for line draw.
;
mov bx,ScanWidth
sub bx,[bp+10]
mov [bp-10], bx ; Amount to skip to get to next line
mov di, ax ; Offset in di
mov ax,[bp+14]
mov ah,al ; ax has duplicated pixel value in al and ah
even
linestart:
mov cx,BlockEnd ; Last point in counter
sub cx,di ; cx has number of bytes till block change
mov bx,[bp+10] ; bx has number of bytes in line
dec bx
cmp bx,cx
ja l1
mov cx,bx ; Won't need a block change
l1:
sub bx,cx ; ax has number of words after block change
inc cx
ror cx,1
ror bx,1
;
; Draw the line
;
even
l4:
cld
rep stosw
cmp di,0 ; Check for exact alignment
je l5
cmp bx,0
je l6
;
; Handle block change and continue
;
l5:
inc dx
push dx
call vgablock
pop dx
cmp bx,0
je l6
mov cx,bx
xor bx,bx
xor di,di
jmp l4
;
; Set up for next line
;
l6:
dec word ptr [bp+12]
je l7
add di,[bp-10] ; Go to start of next line
jnc linestart
inc dx ; Bump block pointer
push dx
call vgablock
pop dx
jmp linestart
;
; Finish up
;
l7:
add sp,2
Postfix
vgafill endp
;
; Copy a given rectangle into display memory at the specified address.
; All pixels from the source rectangle are copied with no masking.
; Coordinates are assumed to be correct and wraparound accounted for by
; the calling routine. The start address and rectangle width are assumed
; to be even values to permit faster copy. The passed values may be modified
; and should not be retained by the calling routine.
;
; Parameters:
; - Far pointer to source rectangle
; - Total width of source memory
; - Row for upper left corner
; - Column for upper left corner
; - Width of rectangle
; - Height of rectangle
;
; Locals
; [bp-10] LineSkip
;
vgarect proc far
Prefix
sub sp,2
;
mov ax,vgadata ; Load address of data segment
mov ds,ax ; Set DS register
;
; Load window pointers
;
mov ax,WinAddr
mov es,ax ; Set ES to point to video memory
push [bp+14]
push [bp+12]
call vgaoffset
add sp,4
;
; Setup control parameters for line draw.
;
mov di, ax ; Offset for output memory in di
mov bx,ScanWidth
sub bx,[bp+16]
mov [bp-10], bx ; Amount to skip to get to next line on output
mov bx,[bp+10]
sub bx,[bp+16]
mov [bp+10], bx ; Amount to go to next line on input data
mov si, [bp+6] ; Offset for input memory
even
linestart:
mov cx,BlockEnd ; Last point in counter
sub cx,di ; cx has number of bytes till block change
mov bx,[bp+16] ; bx has number of bytes in line
dec bx
cmp bx,cx
ja l1
mov cx,bx ; Won't need a block change
l1:
sub bx,cx ; bx has number of words after block change
inc cx
ror cx,1
ror bx,1
;
; Draw the line
;
even
l4:
push ds ; Save segment for vgadata
mov ax, [bp+8]
mov ds,ax ; Set segment for source rectangle
cld
rep movsw
pop ds ; Get segment for vgadata
cmp di,0 ; Check for exact alignment
je l5
cmp bx,0
je l6
;
; Handle block change and continue
;
l5:
inc dx
push dx
call vgablock
pop dx
cmp bx,0
je l6
mov cx,bx
xor bx,bx
xor di,di
jmp l4
;
; Set up for next line
;
l6:
dec word ptr [bp+18]
je l7
add si,[bp+10] ; Goto next line in input
add di,[bp-10] ; Go to start of next line on output
jnc linestart
inc dx ; Bump block pointer
push dx
call vgablock
pop dx
jmp linestart
;
; Finish up
;
l7:
add sp,2
Postfix
vgarect endp
vgacode ends
end